home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / MacPerl 5.1.3 / Mac_Perl_513_src / perl5.002 / missing.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-17  |  12.3 KB  |  675 lines  |  [TEXT/MPS ]

  1. /* $Header: tyrathect:Development:Perl::RCS:missing.c,v 1.2 1994/05/04 02:12:43 neeri Exp $
  2.  *
  3.  *    Copyright (c) 1991-1994 Matthias Neeracher
  4.  *
  5.  *    You may distribute under the terms of the Perl Artistic License,
  6.  *    as specified in the README file.
  7.  *
  8.  * $Log: missing.c,v $
  9.  * Revision 1.2  1994/05/04  02:12:43  neeri
  10.  * Added gmtime(), enabled utime(), reduced spinning.
  11.  *
  12.  * Revision 1.1  1994/03/01  23:38:17  neeri
  13.  * Initial revision
  14.  *
  15.  */
  16.  
  17. /* NEVER try including perl.h here ! */
  18.  
  19. /* DISPATCH_START */
  20. #define MAC_CONTEXT
  21. #define MP_EXT
  22. #define MP_INIT(x) = x
  23.  
  24. #include <time.h>
  25. #include <stdio.h>
  26. #include <AppleEvents.h>
  27. #include <Folders.h>
  28. #include <Events.h>
  29. #include <OSUtils.h>
  30. #include <LowMem.h>
  31. #include <GUSI.h>
  32. #include <TFileSpec.h>
  33. #include <TFileGlob.h>
  34. #include <fp.h>
  35. #include <LowMem.h>
  36.  
  37. #define MEM_SIZE    Size_t
  38.  
  39. #include "config.h"
  40. #include "handy.h"
  41. #include "macish.h"
  42. #include "SubLaunch.h"
  43. #include "embed.h"
  44. /* DISPATCH_END */
  45.  
  46. /* Calls that don't exist on the mac */
  47.  
  48. /* Borrowed from msdos.c
  49.  * Just pretend that everyone is a superuser
  50.  */
  51. /* DISPATCH_START */
  52. #define ROOT_UID    0
  53. #define ROOT_GID    0
  54. int
  55. (getuid)(void)
  56. {
  57.     return ROOT_UID;
  58. }
  59.  
  60. int
  61. (geteuid)(void)
  62. {
  63.     return ROOT_UID;
  64. }
  65.  
  66. int
  67. (getgid)(void)
  68. {
  69.     return ROOT_GID;
  70. }
  71.  
  72. int
  73. (getegid)(void)
  74. {
  75.     return ROOT_GID;
  76. }
  77.  
  78. int
  79. (setuid)(int uid)
  80.     return (uid==ROOT_UID?0:-1);
  81. }
  82.  
  83. int
  84. setgid(int gid)
  85.     return (gid==ROOT_GID?0:-1); 
  86. }
  87.  
  88. #undef execv
  89.  
  90. (execv)()
  91. {
  92.     croak("execv() not implemented on the Macintosh");
  93. }
  94.  
  95. #undef execvp
  96.  
  97. (execvp)()
  98. {
  99.     croak("execvp() not implemented on the Macintosh");
  100. }
  101.  
  102. kill()
  103. {
  104.     croak("kill() not implemented on the Macintosh");
  105. }
  106. /* DISPATCH_END */
  107.  
  108. char **environ;
  109. static    char *    gEnvpool;
  110. extern int StandAlone;
  111.  
  112. char ** init_env(char ** env)
  113. {
  114.     int        envcnt    =    0;
  115.     int        envsize    =    0;
  116.     int        varlen;
  117.     char *    envpool;
  118.     FILE *    envfile    =    0;
  119.     
  120.     for (envcnt = 0; env[envcnt]; envcnt++)    {
  121.         varlen    = strlen(env[envcnt]);
  122.         envsize    +=    varlen+strlen(env[envcnt]+varlen+1)+2;
  123.     }
  124.     
  125.     if (gEnvpool) {
  126.         Safefree(environ);
  127.         Safefree(gEnvpool);
  128.     }
  129.     
  130.     New(50, environ, envcnt+1, char *);
  131.     New(50, gEnvpool, envsize, char);
  132.     
  133.     envpool = gEnvpool;
  134.     for (envcnt = 0; env[envcnt]; envcnt++)    {
  135.         environ[envcnt]     = envpool;
  136.         varlen                = strlen(env[envcnt]);
  137.         strcpy(envpool, env[envcnt]);
  138.         envpool              += varlen+1;
  139.         envpool[-1]            = '=';
  140.         strcpy(envpool, env[envcnt]+varlen+1);
  141.         envpool              += strlen(env[envcnt]+varlen+1)+1;
  142.     }
  143.  
  144.     environ[envcnt] = 0;
  145.     
  146.     return environ;
  147. }    
  148.  
  149. void install_env(Handle env)
  150. {
  151.     int        envcnt    =    0;
  152.     int        envsize    =    0;
  153.     int        varlen;
  154.     char *    envpool;
  155.     char *     max;
  156.     char         state;
  157.     FILE *    envfile    =    0;
  158.     
  159.     if (gEnvpool) {
  160.         Safefree(environ);
  161.         Safefree(gEnvpool);
  162.     }
  163.  
  164.     New(50, gEnvpool, GetHandleSize(env), char);
  165.     
  166.     state = HGetState(env);
  167.     HLock(env);
  168.     BlockMove(*env, (Ptr)gEnvpool, GetHandleSize(env));
  169.     HSetState(env, state);
  170.     
  171.     envpool = gEnvpool;
  172.     max = envpool + GetHandleSize(env);
  173.     while (envpool < max) {
  174.         ++envcnt;
  175.         envpool += strlen(envpool)+1;
  176.     }
  177.     
  178.     New(50, environ, envcnt+1, char *);
  179.     
  180.     envpool = gEnvpool;
  181.     envcnt  = 0;
  182.     while (envpool < max) {
  183.         environ[envcnt++]     = envpool;
  184.         envpool                    += strlen(envpool)+1;
  185.     }
  186.  
  187.     environ[envcnt] = 0;
  188. }
  189.  
  190. Handle retrieve_env()
  191. {
  192.     char ** envp = environ;
  193.     Handle  env  = NewHandle(0);
  194.     
  195.     while (*envp) {
  196.         PtrAndHand(*envp, env, strlen(*envp)+1);
  197.         ++envp;
  198.     }
  199.     
  200.     return env;
  201. }
  202.  
  203. typedef struct PD {
  204.     struct PD *    next;
  205.     FILE *        tempFile;
  206.     FSSpec        pipeFile;
  207.     char *        execute;
  208.     long            status;
  209. } PipeDescr, *PipeDescrPtr;
  210.  
  211. static PipeDescrPtr    pipes        =    nil;
  212. static Boolean            sweeper    =    false;
  213.  
  214. void sweep()
  215. {
  216.     while (pipes)
  217.         my_pclose(pipes->tempFile);
  218.     sweeper = false;
  219. }
  220.  
  221. typedef struct WEPDesc {
  222.     struct WEPDesc *    next;
  223.     const char *                            command;
  224.     EmulationProc                             proc;
  225. } WEPDesc, * WEPDescPtr;
  226.  
  227. static WEPDescPtr         gEmulators[128];
  228. static Boolean            gHasEmulators = false;
  229.  
  230. void AddWriteEmulationProc(const char * command, EmulationProc proc)
  231. {
  232.     WEPDescPtr    wepdesc     = (WEPDescPtr) malloc(sizeof(WEPDesc));
  233.     
  234.     wepdesc->next             =     gEmulators[*command];
  235.     wepdesc->command        =    command;
  236.     wepdesc->proc            =    proc;
  237.     gEmulators[*command]    =    wepdesc;
  238. }
  239.  
  240. EmulationProc FindWriteEmulationProc(char * command, char ** rest)
  241. {
  242.     char *         end;
  243.     WEPDescPtr    queue;
  244.     
  245.     for (end = command; isalnum(*end); ++end);
  246.     
  247.     if (end == command || (*command & 0x80))
  248.         return nil;
  249.     
  250.     for (queue = gEmulators[*command]; queue; queue = queue->next)
  251.         if (!strncmp(command, queue->command, end-command))
  252.             if (!queue->command[end-command]) {
  253.                 while (isspace(*end))
  254.                     ++end;
  255.                 *rest = end;
  256.                 
  257.                 return queue->proc;
  258.             }
  259.     
  260.     return nil;
  261. }
  262.  
  263. static int EmulatePwd(FILE * tempFile, char * command)
  264. {
  265.     char curdir[256];
  266.     
  267.     if (!getcwd(curdir, 256)) 
  268.         return -1;
  269.     
  270.     fprintf(tempFile, "%s\n", curdir);
  271.     
  272.     return 0;
  273. }
  274.  
  275. static int EmulateHostname(FILE * tempFile, char * command)
  276. {
  277.     char curhostname[256];
  278.     
  279.     if (gethostname(curhostname, 256)) 
  280.         return -1;
  281.     
  282.     fprintf(tempFile, "%s\n", curhostname);
  283.     
  284.     return 0;
  285. }
  286.  
  287. static int EmulateGlob(FILE * tempFile, char * command)
  288. {
  289.     char             curbuf[256];
  290.     char *        curcmd;
  291.     Boolean        relativePath;
  292.     int            colonCount;
  293.     FileGlobRef    glob;
  294.     FSSpec         spec;
  295.     FSSpec        curDir;
  296.     
  297.     for (curcmd = curbuf; !isspace(*command); )
  298.         if (!(*curcmd++ = *command++))
  299.             break;
  300.  
  301.     if (!(glob = NewFileGlob(curbuf)))
  302.         return -1;
  303.     
  304.     relativePath = true;
  305.     
  306.     if (curbuf[0] == ':') {
  307.         /* Explicitely relative path, e.g. <:*.c> */
  308.         char     ch;
  309.         
  310.         for (curcmd = curbuf+1; *curcmd == ':'; ++curcmd)
  311.             ;
  312.         
  313.         ch             = *curcmd; 
  314.         *curcmd        = 0;
  315.         Path2FSSpec(curbuf, &curDir);
  316.         *curcmd        = ch;
  317.         colonCount     =    curcmd - curbuf;
  318.     } else if (!strchr(curbuf, ':')) {
  319.         /* Implicitely relative path, e.g. <*.c> */
  320.         colonCount     =     0;
  321.         Path2FSSpec(":", &curDir);
  322.     } else
  323.         relativePath = false;
  324.         
  325.     while (FileGlob2FSSpec(glob, &spec)) {
  326.         if (relativePath) {
  327.             curcmd = FSp2DirRelPath(&spec, &curDir);
  328.             if (colonCount) {
  329.                 int i = colonCount - (*curcmd == ':');
  330.                 while (i--)
  331.                     putc(':', tempFile);
  332.             }
  333.         } else
  334.             curcmd = FSp2FullPath(&spec);
  335.         
  336.         fprintf(tempFile, "%s\n", curcmd);
  337.         NextFileGlob(glob);
  338.     }
  339.     DisposeFileGlob(glob);
  340.     
  341.     return 0;
  342. }
  343.  
  344. FILE * my_popen(char * command, char * mode)
  345. {
  346.     PipeDescrPtr    pipe;
  347.     
  348.     if (!gHasEmulators) {
  349.         gHasEmulators = true;
  350.         AddWriteEmulationProc("pwd", EmulatePwd);
  351.         AddWriteEmulationProc("directory", EmulatePwd);
  352.         AddWriteEmulationProc("Directory", EmulatePwd);
  353.         AddWriteEmulationProc("hostname", EmulateHostname);
  354.         AddWriteEmulationProc("glob", EmulateGlob);
  355.     }
  356.     
  357.     if (!strcmp(command, "-"))
  358.         croak("Implicit fork() on a Mac? No forking chance");
  359.     
  360.     New(666, pipe, 1, PipeDescr);
  361.     
  362.     if (!pipe)
  363.         return NULL;
  364.         
  365.     if (FSpMakeTempFile(&pipe->pipeFile))
  366.         goto failed;
  367.     pipe->execute    =    nil;
  368.     
  369.     switch(*mode)    {
  370.     case 'r':
  371.         {
  372.             /* Ugh ! A hardcoded command  ! */
  373.             EmulationProc proc = FindWriteEmulationProc(command, &command);
  374.             
  375.             if (proc) {
  376.                 if (!(pipe->tempFile    = fopen(FSp2FullPath(&pipe->pipeFile), "w")))
  377.                     goto delete;
  378.                 if (proc(pipe->tempFile, command))
  379.                     goto delete;
  380.                 fclose(pipe->tempFile);
  381.             } else if (SubLaunch(command, nil, &pipe->pipeFile, &pipe->pipeFile, &pipe->status))
  382.                 goto delete;
  383.             
  384.             if (!(pipe->tempFile    = fopen(FSp2FullPath(&pipe->pipeFile), "r")))
  385.                 goto delete;
  386.             break;
  387.         }
  388.     case 'w':
  389.         New(667, pipe->execute, strlen(command)+1, char);
  390.         if (!pipe->execute || !(pipe->tempFile    = fopen(FSp2FullPath(&pipe->pipeFile), "w")))
  391.             goto delete;
  392.         strcpy(pipe->execute, command);
  393.         break;
  394.     }
  395.     
  396.     pipe->next    =    pipes;
  397.     pipes            =    pipe;
  398.     
  399.     if (!sweeper)    {
  400.         atexit(sweep);
  401.         sweeper    =    true;
  402.     }
  403.  
  404.     return pipe->tempFile;
  405. delete:
  406.     if (pipe->execute)
  407.         Safefree(pipe->execute);
  408.     HDelete(pipe->pipeFile.vRefNum, pipe->pipeFile.parID, pipe->pipeFile.name);
  409. failed:
  410.     Safefree(pipe);
  411.     
  412.     return NULL;
  413. }
  414.  
  415. int my_pclose(FILE *    f)
  416. {
  417.     OSErr                err;
  418.     PipeDescrPtr *    prev;
  419.     PipeDescrPtr    pipe;
  420.     
  421.     for (prev = (PipeDescrPtr *) &pipes; pipe = *prev; prev = &pipe->next)
  422.         if (pipe->tempFile == f)
  423.             break;
  424.     
  425.     if (!pipe)
  426.         return -1;
  427.     
  428.     *prev = pipe->next;
  429.     
  430.     fclose(f);
  431.     
  432.     if (pipe->execute)
  433.         err = SubLaunch(pipe->execute, &pipe->pipeFile, nil, nil, &pipe->status);
  434.     else
  435.         err = noErr;
  436.         
  437.     HDelete(pipe->pipeFile.vRefNum, pipe->pipeFile.parID, pipe->pipeFile.name);
  438.     if (pipe->execute)
  439.         Safefree(pipe->execute);
  440.     Safefree(pipe);
  441.     
  442.     return err? -1 : (int) pipe->status;    
  443. }
  444.  
  445. #undef TUNESPIN
  446.  
  447. void SpinMacCursor()
  448. {
  449.     static long lastSpin = 0;
  450.     static long lastAevt = 0;
  451. #ifdef TUNESPIN
  452.     static long numSpins = 0;
  453. #endif
  454.     long            curSpin    = LMGetTicks();
  455.  
  456. #ifdef TUNESPIN
  457.     ++numSpins;
  458. #endif
  459.     if (curSpin - lastSpin < 5)
  460.         return;
  461.     
  462. #ifdef TUNESPIN
  463.     printf("%d %d, ", curSpin, numSpins);
  464. #endif
  465.     lastSpin = curSpin;
  466.     
  467.     sleep(0);
  468.     
  469.     if (!StandAlone && curSpin - lastAevt > 30) {
  470.         /* Newer versions of the MPW Shell disable automatic processing of
  471.            AppleEvents, but we want them!
  472.         */
  473.         EventRecord ev;
  474.         
  475.         lastAevt = curSpin;
  476.         if (WaitNextEvent(highLevelEventMask, &ev, 0, nil)) {
  477.              AEProcessAppleEvent(&ev);    /* Ignore errors */
  478.              lastAevt -= 25;                 /* Retry sooner if successful */
  479.         }
  480.     }
  481. }
  482.  
  483. /* DISPATCH_START */
  484. struct tm *localtime(const time_t *tp)
  485.     {
  486.     DateTimeRec dtr;
  487.     MachineLocation loc;
  488.     static struct tm statictime;
  489.     static const short monthday[12] =
  490.         {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
  491.  
  492.     Secs2Date(*tp, &dtr);
  493.     statictime.tm_sec = dtr.second;
  494.     statictime.tm_min = dtr.minute;
  495.     statictime.tm_hour = dtr.hour;
  496.     statictime.tm_mday = dtr.day;
  497.     statictime.tm_mon = dtr.month - 1;
  498.     statictime.tm_year = dtr.year - 1900;
  499.     statictime.tm_wday = dtr.dayOfWeek - 1;
  500.     statictime.tm_yday = monthday[statictime.tm_mon]
  501.         + statictime.tm_mday - 1;
  502.     if (1 < statictime.tm_mon && !(statictime.tm_year & 3))
  503.         ++statictime.tm_yday;
  504.     ReadLocation(&loc);
  505.     if (!loc.latitude && !loc.longitude)
  506.         statictime.tm_isdst = -1;
  507.     else
  508.         statictime.tm_isdst = (loc.u.dlsDelta & 0x80) != 0;
  509.     return(&statictime);
  510. }
  511.  
  512. struct tm * gmtime(const time_t * timer)
  513. {
  514.     MachineLocation     loc;
  515.     long                    delta;
  516.     time_t                rolex;
  517.     
  518.     ReadLocation(&loc);
  519.     
  520.     if (!loc.latitude && !loc.longitude)
  521.         return localtime(timer);    /* This is incorrect unless you live in Greenwich */
  522.     
  523.     delta = loc.u.gmtDelta & 0xFFFFFF;
  524.     
  525.     if (delta & 0x800000)
  526.         delta = (long) ((unsigned long) delta | 0xFF000000);
  527.         
  528.     rolex = (unsigned long) ((long) *timer - delta);
  529.     
  530.     return localtime(&rolex);
  531.  }
  532. /* DISPATCH_END */
  533.  
  534. clock_t mac_times(struct tms * t)
  535. {
  536.     t->tms_utime = clock() - gStartClock;
  537.     t->tms_stime = 0;
  538.     t->tms_cutime = 0;
  539.     t->tms_cstime = 0;
  540.     
  541.     return t->tms_utime;
  542. }
  543.  
  544. #undef atof
  545.  
  546. double mac_atof(const char * nptr)
  547. {
  548.     /* The Mac returns NaN(17) on undefined strings, which is not acceptable
  549.        for Perl
  550.     */
  551.     double res = atof(nptr);
  552.     
  553.     if (isnan(res) /* This doesn't work: && res == nan("17") */)
  554.         return 0.0;
  555.     else
  556.         return res;
  557. }
  558.  
  559. void CopyC2PStr(char * cstr, StringPtr pstr)
  560. {
  561.     int    len;
  562.     
  563.     for (len = 0; *cstr && len<256; )
  564.         pstr[++len] = *cstr++;
  565.     
  566.     pstr[0] = len;
  567. }
  568.  
  569.  
  570. char * MPWFileName(char * file)
  571. {
  572.     if (!strcmp(file, "Dev:Pseudo"))
  573.         return gPseudoFileName;
  574.     else if (!strncmp(file, "Dev:Pseudo:", 11))
  575.         return file + 11;
  576.     else
  577.         return file;
  578. }
  579.  
  580. static Boolean sPosCommit = true;
  581.  
  582. char * MPWPosIndication(char * buf, char * file, long line)
  583. {
  584.     file = MPWFileName(file);
  585.  
  586.     if (!sPosCommit)
  587.        gFirstErrorLine = -1;
  588.         
  589.     if (gFirstErrorLine == -1 && !Path2FSSpec(file, &gFirstErrorFile)) {
  590.         gFirstErrorLine = line;
  591.         sPosCommit      = false;
  592.      }
  593.     
  594.     strcpy(buf, "File '"); 
  595.     buf += 6;
  596.     
  597.     while (*file) 
  598.         if (*file == '\'') {
  599.         strcpy(buf, "'∂''");
  600.         buf += 3;
  601.         ++file;
  602.     } else
  603.         *buf++ = *file++;
  604.         
  605.     if (buf[-1] == '\'' && buf[-2] == '\'')
  606.         --buf;
  607.     else
  608.         *buf++ = '\'';
  609.  
  610.     return buf + sprintf(buf, "; Line %ld", line);
  611. }
  612.  
  613. void     MPWPosCommit()
  614. {
  615.     sPosCommit = true;
  616. }
  617.  
  618. int OverrideExtract(char * origname)
  619. {
  620.     char         file[256];
  621.     
  622.     strcpy(file+1, MPWFileName(origname));
  623.     file[0] = strlen(file+1);
  624.     ParamText((StringPtr) file, "\p", "\p", "\p");
  625.     
  626.     return Alert(270, (ModalFilterUPP) nil) == 1;
  627. }
  628.  
  629. #define STACK_INTERVENTION_LIMIT    8192
  630.  
  631. void StackAttack()
  632. {
  633.     if (StackSpace() < STACK_INTERVENTION_LIMIT)
  634.         croak("Stack space getting low ! Aborting script for your own good...\n");
  635. }
  636.  
  637. void mac_initminiperl()
  638. {
  639.     if (!gAppDir) {
  640.         InitGraf((Ptr) &qd.thePort);
  641.         signal(SIGINT, SIG_DFL);
  642.     }
  643.     
  644.     gStartClock      = LMGetTicks();
  645. }
  646.  
  647. /* DISPATCH_START */
  648. pid_t (getpid)()
  649. {
  650.     return 1;
  651. }
  652. /* DISPATCH_END */
  653.  
  654. void SIOUXHandleOneEvent()
  655. {
  656.     Debugger();
  657. }
  658.  
  659. void InstallConsole()
  660. {
  661.     Debugger();
  662. }
  663.  
  664. void WriteCharsToConsole()
  665. {
  666.     Debugger();
  667. }
  668.  
  669. void ReadCharsFromConsole()
  670. {
  671.     Debugger();
  672. }
  673.